package br.inf.solutions.apresentacoes.ssp.view.composer;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.springframework.context.annotation.Scope;
import org.zkoss.image.AImage;
import org.zkoss.util.media.Media;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Div;
import org.zkoss.zul.Image;
import org.zkoss.zul.Textbox;

import br.com.vexillum.control.manager.ExceptionManager;
import br.com.vexillum.control.util.Attachment;
import br.com.vexillum.util.HibernateUtils;
import br.com.vexillum.util.ImageUtils;
import br.com.vexillum.util.ReflectionUtils;
import br.com.vexillum.util.Return;
import br.com.vexillum.util.SpringFactory;
import br.com.vexillum.util.ZKUtils;
import br.inf.solutions.apresentacoes.ssp.control.PersonController;
import br.inf.solutions.apresentacoes.ssp.control.PostGraduationController;
import br.inf.solutions.apresentacoes.ssp.control.SearchPersonController;
import br.inf.solutions.apresentacoes.ssp.control.SquareController;
import br.inf.solutions.apresentacoes.ssp.control.basics.CriterionPromotionController;
import br.inf.solutions.apresentacoes.ssp.control.basics.EyeColorController;
import br.inf.solutions.apresentacoes.ssp.control.basics.HairColorController;
import br.inf.solutions.apresentacoes.ssp.control.basics.SkinColorController;
import br.inf.solutions.apresentacoes.ssp.control.basics.TypeBaldnessController;
import br.inf.solutions.apresentacoes.ssp.model.Person;
import br.inf.solutions.apresentacoes.ssp.model.PostGraduation;
import br.inf.solutions.apresentacoes.ssp.model.Square;
import br.inf.solutions.apresentacoes.ssp.model.SquarePostGraduation;
import br.inf.solutions.apresentacoes.ssp.model.State;
import br.inf.solutions.apresentacoes.ssp.model.basics.CriterionPromotion;
import br.inf.solutions.apresentacoes.ssp.model.basics.EyeColor;
import br.inf.solutions.apresentacoes.ssp.model.basics.HairColor;
import br.inf.solutions.apresentacoes.ssp.model.basics.SkinColor;
import br.inf.solutions.apresentacoes.ssp.model.basics.TypeBaldness;
import br.inf.solutions.apresentacoes.ssp.model.bulletin.items.FunctionPerson;
import br.inf.solutions.apresentacoes.ssp.model.enums.Behavior;
import br.inf.solutions.apresentacoes.ssp.model.enums.BloodType;
import br.inf.solutions.apresentacoes.ssp.model.enums.CategoryReservist;
import br.inf.solutions.apresentacoes.ssp.model.enums.CivilState;
import br.inf.solutions.apresentacoes.ssp.model.enums.DriverLicenseCategory;
import br.inf.solutions.apresentacoes.ssp.model.enums.NumberHat;
import br.inf.solutions.apresentacoes.ssp.model.enums.NumberPants;
import br.inf.solutions.apresentacoes.ssp.model.enums.NumberShirt;
import br.inf.solutions.apresentacoes.ssp.model.enums.NumberShoes;
import br.inf.solutions.apresentacoes.ssp.model.enums.OrganShipper;
import br.inf.solutions.apresentacoes.ssp.model.enums.Schooling;
import br.inf.solutions.apresentacoes.ssp.model.hierarchy.HierarchyStructEntity;
import br.inf.solutions.apresentacoes.ssp.view.attachment.AttachmentPerson;
import br.inf.solutions.apresentacoes.ssp.view.validator.ImageValidator;

@SuppressWarnings("serial")
@org.springframework.stereotype.Component
@Scope("prototype")
public class PersonComposer extends	BaseAddressComposer<Person, PersonController> {

	private Integer stepControl = 0;
	private Square searchSquare;
	private List<FunctionPerson> fp;
	private HashMap<String, String> mapPages;
	private List<Long> listaID;	
	private HierarchyStructEntity unity;
	private Media photoPerson;
	private String lenghtList; 
	
	@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		initMapPages();
		
		if(parentComposer != null){
			setFp(((PersonComposer) parentComposer).getFp());			
			lenghtList = "Total de Pessoas: " + ((PersonComposer) parentComposer).getFp().size();		
		}
		
		loadBinder();
	}

	private void initMapPages() {
		mapPages = new HashMap<>();
		getMapPages().put("0", "step0");
		getMapPages().put("1", "step1");
		getMapPages().put("2", "step2");
		getMapPages().put("3", "step3");
		getMapPages().put("4", "step4");
		getMapPages().put("5", "step5");
	}

	public Return searchPerson() {
		Return ret = getControl().doAction("getPersonByCPF");
		if (ret.isValid()) {
			if (ret.getList() != null && !ret.getList().isEmpty()) {
				setEntity((Person) ((Person) ret.getList().get(0)).cloneEntity());
			} else {
				setEntity(new Person(getEntity().getCpf()));
				setSearchSquare(null);
			}
			initPagePerson();
		}
		return ret;
	}
	
	public Return getPersonByRG() {
		SearchPersonController<?> sp = SpringFactory.getController("searchPersonController", SearchPersonController.class, null);

		Person person = sp.getPerson(getEntity().getRg());
		if (person!=null) {
			setEntity(person);
			initPagePerson();
		}
		
		return new Return(true);
	}
	
	
	private void initPagePerson() {
		goToNextStep();
		loadBinder();
		loadComboboxes();
		loadSquarePostComboboxes();
		showPersonPhoto((Image) getComponentById("personPhoto"), getEntity());
		((HtmlBasedComponent) getComponentById("lblUpdatePhoto")).setStyle(((HtmlBasedComponent) getComponentById("lblUpdatePhoto")).getStyle() + ";display: none;");
	
	}

	public Return firstStep() {
		Return ret = getControl().doAction("firstStep");
		if (ret.isValid()) {
			setEntity((Person) getControl().doAction("getPersonByCPF")
					.getList().get(0));
			uploadPersonImage(getPhotoPerson(), entity);
			goToNextStep();
		}
		return ret;
	}

	public Return secondStep() {
		Return ret = getControl().doAction("secondStep");
		if (ret.isValid()) {
			goToNextStep();
		}
		return ret;
	}

	public Return thirdStep() {
		Return ret = getControl().doAction("thirdStep");
		if (ret.isValid()) {
			goToNextStep();
		}
		return ret;
	}

	public Return fourthStep() {
		Return ret = getControl().doAction("fourthStep");
		if (ret.isValid()) {
			goToNextStep();
		}
		return ret;
	}

	public Return fifthStep() {
		Return ret = getControl().doAction("fifthStep");
		if (ret.isValid()) {
			goToFirstStep();
			clearForm();
			loadBinder();
		}
		return ret;
	}

	public void goToNextStep() {
		stepControl += 1;
		goToStep(stepControl);
	}

	public void goToPreviousStep() {
		stepControl -= 1;
		goToStep(stepControl);
	}

	public void goToFirstStep() {
		stepControl = 0;
		goToStep(stepControl);
	}

	private void goToStep(Integer step) {
		setVisibleSteps(step);
		// loadBinder();
	}

	private void setVisibleSteps(Integer step) {
		for (String s : getMapPages().keySet()) {
			Div div = (Div) getComponentById("step" + s);
			if (step == Integer.parseInt(s)) {
				div.setVisible(true);
			} else {
				div.setVisible(false);
			}
		}
	}
	
	public void changePersonImage(UploadEvent event){
        Media media = event.getMedia();
        ImageValidator val = new ImageValidator(media);
        Return ret = val.upload();
        if(ret.isValid()){
        	try {
        		AImage image = (AImage) media;
        		InputStream image1 = ZKUtils.mediaToStream(media);
    			if(image.getHeight() > 117 || image.getWidth() > 114){
    				image1 = ImageUtils.scaleImage(image1, 114, 117, image.getFormat());
    			}
    			image = new AImage("photo", image1);
				setPhotoPerson(image);
				((Image)getComponentById("personPhoto")).setContent(image);
//	            uploadPersonImage(media, entity).isValid();
			} catch (Exception e) {
				ret.concat(new ExceptionManager(e).treatException());
			}
        }
        treatReturn(ret);
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Return uploadPersonImage(Media file, Person person){
		Return ret = new Return(true);
		if(file != null){
			Attachment att = new AttachmentPerson();
			try {
				att.uploadAttachment(ZKUtils.mediaToStream(file), "photo", person);
			} catch (Exception e) {
				ret.concat(new ExceptionManager(e).treatException());
			}
		}
		return ret;
	}

	@SuppressWarnings("unchecked")
	public List<Square> getSquares() {
		SquareController controlador = SpringFactory.getController("squareController", SquareController.class,	ReflectionUtils.prepareDataForPersistence(this));
		return (List<Square>) controlador.doAction("listAll").getList();
	}

	@SuppressWarnings("unchecked")
	public List<PostGraduation> getPosts() {
		if (searchSquare == null) {
			return new ArrayList<PostGraduation>();
		} else {
			getEntity().setSquare(searchSquare);
			List<PostGraduation> list = new ArrayList<>();
//			getControl().refresh(searchSquare);
			for (SquarePostGraduation sqp : searchSquare.getSquarePostAssociations()) {
				PostGraduation post = (PostGraduation) HibernateUtils.initialize(sqp.getPostGraduation());
				list.add(post);
			}
			HashMap<String, Object> data = new HashMap<>();
			data.put("listEntity", list);
			PostGraduationController controller = SpringFactory.getController("postGraduationController", PostGraduationController.class,	data);
			return (List<PostGraduation>) controller.doAction("sortListByPattern").getList();
		}

	}

	@SuppressWarnings("unchecked")
	public List<CriterionPromotion> getCriterions() {
		CriterionPromotionController controlador = SpringFactory.getController("criterionPromotionController",CriterionPromotionController.class,ReflectionUtils.prepareDataForPersistence(this));
		return (List<CriterionPromotion>) controlador.doAction("listAll").getList();
	}
	
	public List<Behavior> getBehavior() {
		return Arrays.asList(Behavior.values());
	}

	public List<DriverLicenseCategory> getDriverCategories() {
		return Arrays.asList(DriverLicenseCategory.values());
	}

	public List<CivilState> getCivilStates() {
		return Arrays.asList(CivilState.values());
	}

	public List<Schooling> getSchoolings() {
		return Arrays.asList(Schooling.values());
	}

	@SuppressWarnings("unchecked")
	public List<SkinColor> getSkinColors() {
		SkinColorController controlador = SpringFactory.getController("skinColorController", SkinColorController.class,ReflectionUtils.prepareDataForPersistence(this));
		return (List<SkinColor>) controlador.doAction("listAll").getList();
	}

	@SuppressWarnings("unchecked")
	public List<HairColor> getHairColors() {
		HairColorController controlador = SpringFactory.getController("hairColorController", HairColorController.class,ReflectionUtils.prepareDataForPersistence(this));
		return (List<HairColor>) controlador.doAction("listAll").getList();
	}

	@SuppressWarnings("unchecked")
	public List<EyeColor> getEyeColors() {
		EyeColorController controlador = SpringFactory.getController("eyeColorController", EyeColorController.class,	ReflectionUtils.prepareDataForPersistence(this));
		return (List<EyeColor>) controlador.doAction("listAll").getList();
	}

	@SuppressWarnings("unchecked")
	public List<TypeBaldness> getTypeBaldnesses() {
		TypeBaldnessController controlador = SpringFactory.getController("typeBaldnessController", TypeBaldnessController.class,ReflectionUtils.prepareDataForPersistence(this));
		return (List<TypeBaldness>) controlador.doAction("listAll").getList();
	}

	public List<BloodType> getBloodTypes() {
		return Arrays.asList(BloodType.values());
	}

	public List<NumberShoes> getNumberShoes() {
		return Arrays.asList(NumberShoes.values());
	}

	public List<NumberPants> getNumberPants() {
		return Arrays.asList(NumberPants.values());
	}

	public List<NumberShirt> getNumberShirts() {
		return Arrays.asList(NumberShirt.values());
	}

	public List<NumberHat> getNumberHats() {
		return Arrays.asList(NumberHat.values());
	}

	public List<OrganShipper> getOrganShippers() {
		return Arrays.asList(OrganShipper.values());
	}

	public List<CategoryReservist> getCategoriesReservist() {
		return Arrays.asList(CategoryReservist.values());
	}

	@Override
	protected void loadComboboxes() {
		Textbox tb;
		Combobox cb;

		tb = (Textbox) getComponentById(component, "fldStateHidden");
		cb = (Combobox) getComponentById(component, "fldState");

		if (tb != null) {
			cb.setValue(tb.getValue());
			setSearchState(new State(tb.getValue()));
		}

		tb = (Textbox) getComponentById(component, "fldCityHidden");
		cb = (Combobox) getComponentById(component, "fldCity");

		if (tb != null) {
			cb.setValue(tb.getValue());
		}

		tb = (Textbox) getComponentById(component, "fldStateHidden2");
		cb = (Combobox) getComponentById(component, "fldState2");

		if (tb != null) {
			cb.setValue(tb.getValue());
		}

		tb = (Textbox) getComponentById(component, "fldCityHidden2");
		cb = (Combobox) getComponentById(component, "fldCityAddress");

		if (tb != null) {
			cb.setValue(tb.getValue());
		}
	}

	protected void loadSquarePostComboboxes() {
		Textbox tb;
		Combobox cb;

		tb = (Textbox) getComponentById(component, "fldSquareHidden");
		cb = (Combobox) getComponentById(component, "fldSquare");

		if (tb != null) {
			cb.setValue(tb.getValue());
			if (getEntity().getSquare() != null) {
				setSearchSquare(HibernateUtils.materializeProxy(getEntity()
						.getSquare()));
			}
		}

		tb = (Textbox) getComponentById(component, "fldPostHidden");
		cb = (Combobox) getComponentById(component, "fldPost");

		if (tb != null) {
			cb.setValue(tb.getValue());
		}

	}

	@Override
	protected String getUpdatePage() {
		return "paginas/pessoa/cadastrar.zul";
	}

	@Override
	protected String getDeactivationMessage() {
		return null;
	}

	@Override
	public PersonController getControl() {
		return SpringFactory.getController("personController", PersonController.class, ReflectionUtils.prepareDataForPersistence(this));
	}

	@Override
	public Person getEntityObject() {
		return new Person();
	}

	@SuppressWarnings("unchecked")
	public Return researchUnity() {
		Return retSearch = new Return(true);
		
		unity = getEntity().getUnity();
		listaID = new ArrayList<Long>();		
		recursivo(unity);		
		retSearch.concat(getControl().doAction("researchPersonFunction"));
		setFp((List<FunctionPerson>) retSearch.getList());
		lenghtList = "Total de Pessoas: " + getFp().size();
		return retSearch;
	}
	
	public void recursivo(HierarchyStructEntity no){
		List<HierarchyStructEntity> filhos;
		
		if(no == null)
			return;

		listaID.add(no.getId());
		if(no.getChildrens() == null || no.getChildrens().size() <= 0){
			return;
		}
		
		filhos = no.getChildrens();
		for (HierarchyStructEntity HSE : filhos) {
			recursivo(HSE);
		}
	}

	@Override
	public Return generateReport() {
//		String[] listItensPerson = new String[]{"rg","fullName"};
//		setFollowAnnotation(false);
//		Map<String, String> mapFieldsNamePerson = new HashMap<>();
//		mapFieldsNamePerson.put("rg", "Registro Geral");
//		mapFieldsNamePerson.put("fullName", "Nome Completo");
//		setMapFieldsName(mapFieldsNamePerson );
//		setListItens(listItensPerson );
		return super.generateReport();
	}
	
	public List<FunctionPerson> getFp() {
		return fp;
	}

	public void setFp(List<FunctionPerson> fp) {
		this.fp = fp;
	}

	public HashMap<String, String> getMapPages() {
		return mapPages;
	}

	public void setMapPages(HashMap<String, String> mapPages) {
		this.mapPages = mapPages;
	}

	public Square getSearchSquare() {
		return searchSquare;
	}

	public void setSearchSquare(Square searchSquare) {
		this.searchSquare = searchSquare;
	}
	
	public List<Long> getListaID() {
		return listaID;
	}

	public void setListaID(List<Long> listaID) {
		this.listaID = listaID;
	}

	public String getLenghtList() {
		return lenghtList;
	}

	public void setLenghtList(String lenghtList) {
		this.lenghtList = lenghtList;
	}

	public Media getPhotoPerson() {
		return photoPerson;
	}

	public void setPhotoPerson(Media photoPerson) {
		this.photoPerson = photoPerson;
	}
}